package com.curluin.scene;

import com.curluin.math.MyVector;
import com.curluin.math.Triangle;
import com.curluin.math.Vertex;

/**
 * @author sh0rtz
 *
 */
public class Cube extends TriangleMesh {

	
	private static final String Log_Tag = "Cube";
	/**
	 * Width of the cube (+X direction).
	 */
	private float width;

	/**
	 * Height of the cube (+Y direction).
	 */
	private float height;

	/**
	 * Length of the cube (+Z direction).
	 */
	private float length;

	/**
	 * Width and length of texture
	 */
	private float[] textureSize = null;
	
	
	private int[] numTexturePerDim = null;

	
	public Cube(MyVector position, float width, float height, float length, MyVector color) {		
		super(position, MyVector.makeVector3(width, height, length), color);
		this.width = width;
		this.height =height;
		this.length =length;
		setColor(color);

		if(this.getClass().equals(Cube.class)) initialize();

		// Up
		generateTexCoords4Vertices(4, 7, 6, 5); // See illustration right to 'buildMesh()'
		// Front
		generateTexCoords4Vertices(3, 7, 6, 2);
		// Back
		generateTexCoords4Vertices(4, 0, 1, 5);
		// Left, right & down are determined by up, front & back as a side effect

		computeNormalsAndRenderStructures();

	}

	

	public Cube(MyVector position, float[] textureSize, int[] numTexturePerDim, MyVector color) {		
		super(position, MyVector.makeVector3(textureSize[0]*numTexturePerDim[0], textureSize[1]*numTexturePerDim[1], textureSize[2]*numTexturePerDim[2]), color);
		this.width = textureSize[0]*numTexturePerDim[0];
		this.height =textureSize[1]*numTexturePerDim[1];
		this.length =textureSize[2]*numTexturePerDim[2];
		this.textureSize = textureSize;
		this.numTexturePerDim=numTexturePerDim;
		setColor(color);

		if(this.getClass().equals(Cube.class)) initialize();
//		for(Vertex v : vertices){
//			Log.e(LOG_TAG, ""+v.coords);
//		}
		
		computeNormalsAndRenderStructures();

	}

	@Override
	protected void buildMesh(){
		if(textureSize!=null&&numTexturePerDim!=null){
			buildFace(1,2,0);
			buildFace(1,2,width);
			buildFace(0,2,0);
			buildFace(0,2,height);
			buildFace(0,1,0);
			buildFace(0,1,length);
			
		}
		else{
			// Vertices
			vertices.add(new Vertex(0, 0, 0));                                // v0       4_____5
			vertices.add(new Vertex(width, 0, 0));                            // v1		  /|   /|
			vertices.add(new Vertex(width, 0,  length));              		  // v2		7/_|__/_|1
			vertices.add(new Vertex(0, 0,  length));                          // v3    h | /0 |6/ 
			vertices.add(new Vertex(0,  height, 0));                          // v4	     |/___|/  l
			vertices.add(new Vertex(width, height, 0));              		  // v5	    3  w   2
			vertices.add(new Vertex(width, height,length));  				  // v6
			vertices.add(new Vertex(0, height,  length));             		  // v7

			// Pack them to triangles
			triangles.add(new Triangle(0, 1, 2));
			triangles.add(new Triangle(0, 2, 3));
			triangles.add(new Triangle(1, 5, 2));
			triangles.add(new Triangle(5, 6, 2));
			triangles.add(new Triangle(5, 4, 6));
			triangles.add(new Triangle(4, 7, 6));
			triangles.add(new Triangle(4, 0, 7));
			triangles.add(new Triangle(0, 3, 7));
			triangles.add(new Triangle(3, 2, 7));
			triangles.add(new Triangle(2, 6, 7));
			triangles.add(new Triangle(1, 0, 4));
			triangles.add(new Triangle(1, 4, 5));
		}
	}

	/* (non-Javadoc)
	 * @see com.curluin.scene.Node#setColor(com.curluin.math.MyVector)
	 */
	@Override
	public void setColor(MyVector color) {
		MyVector newColor = (color.getDimension()==4)? color : MyVector.makeVector4(color.get(0),color.get(1),color.get(2),1);
		for(Vertex v : vertices){
			v.setColor(newColor);
		}
		createRenderStructures();
	}

	private void generateTexCoords4Vertices(int upperLeft, int lowerLeft, int lowerRight, int upperRight){
		this.setTextureCoordinate(upperLeft, 0, 0);
		this.setTextureCoordinate(lowerLeft, 0, 1);
		this.setTextureCoordinate(upperRight, 1, 0);
		this.setTextureCoordinate(lowerRight, 1, 1);
	}

	//	/* (non-Javadoc)
	//	 * @see com.curluin.scene.Node#initializeShape()
	//	 */
	//	@Override
	//	public void initializeShape() {
	//		// TODO Auto-generated method stub
	//		Rectangle shape = new Rectangle(this);
	//		this.aproximateShape = shape;
	//	}
	//	
	private void buildFace(int dim1,int dim2, float shift3rdDim){
		
		int numTextureDim1 = Math.abs(numTexturePerDim[dim1]);
		int numTextureDim2 = Math.abs(numTexturePerDim[dim2]);
		
//		Log.e(LOG_TAG,"num Tex dim1: "+numTextureDim1);
//		Log.e(LOG_TAG,"num Tex dim2: "+numTextureDim2);
		if(numTextureDim1==0||numTextureDim2==0) return;

		float d1Coor = 0;
		float d2Coor = 0;
		int numVerticesBefore=vertices.size();
		for(int i=0; i <= numTextureDim1; i++){
			d2Coor = 0;
			for(int k=0; k <= numTextureDim2; k++){
				Vertex v = new Vertex(0, 0, 0);
				v.coords.set(dim1, d1Coor);
				v.coords.set(dim2, d2Coor);
				v.coords.set(3-dim1-dim2, shift3rdDim);
				vertices.add(v);
//				if(3-dim1-dim2==1)
				String s1 = ""+((dim1==0)? d1Coor : (dim2==0)? d2Coor : shift3rdDim);
				String s2 = ""+((dim1==1)? d1Coor : (dim2==1)? d2Coor : shift3rdDim);
				String s3 = ""+((dim1==2)? d1Coor : (dim2==2)? d2Coor : shift3rdDim);
//					Log.e(LOG_TAG, s1+" "+s2+" "+s3);
				d2Coor+=textureSize[dim2];
			}
			d1Coor+=textureSize[dim1];
		}
		int numVertDim2 = numTextureDim2+1;
		int numVertices =vertices.size();
		for(int i=numVerticesBefore; i<numVertices; i++){
			if((i/numVertDim2)%2==0){
				if(i%numVertDim2==numVertDim2-1)continue;
				if(!(i-numVerticesBefore<numVertDim2)){ triangles.add(new Triangle(i, i+1, i-(numVertDim2)));}//Log.w(LOG_TAG, i+" "+(i+1)+" "+(i-numVertDim2));}
				if(!(i>=numVertices-numVertDim2)){ triangles.add(new Triangle(i, i+1, i+(numVertDim2)));}//Log.w(LOG_TAG, i+" "+(i+1)+" "+(i+numVertDim2));}
			}
			else{
				if(i%numVertDim2==0)continue;
				if(!(i-numVerticesBefore<numVertDim2)){ triangles.add(new Triangle(i, i-1, i-(numVertDim2)));}//Log.w(LOG_TAG, i+" "+(i-1)+" "+(i-numVertDim2));}
				if(!(i>=numVertices-numVertDim2)){ triangles.add(new Triangle(i, i-1, i+(numVertDim2)));}//Log.w(LOG_TAG, i+" "+(i-1)+" "+(i+numVertDim2));}
			}
		
		}
		boolean low,left;
		float tx=0,ty=0;
		for(int i=numVerticesBefore; i<numVertices; i++){
			low=((i-numVerticesBefore)%numVertDim2)%2==0;
			left=((i-numVerticesBefore)/numVertDim2)%2==0;
			if(low&&left){ tx=0;ty=0;}
			else if(low&&!left){ tx=1;ty=0;}
			else if(!low&&left){ tx=0;ty=1;}
			else if(!low&&!left){ tx=1;ty=1;}
			vertices.elementAt(i).texCoords.set(0, tx);
			vertices.elementAt(i).texCoords.set(1, ty);
		}
//		Log.w(LOG_TAG, "NumVertecies: "+numVertices+" numZDir: "+numVertDim2+" numTriangles: "+triangles.size());
	}



}
